package com.hxrfid.web.controller.project;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hxrfid.common.core.controller.BaseController;
import com.hxrfid.common.core.domain.R;
import com.hxrfid.common.core.domain.entity.SysUser;
import com.hxrfid.common.enums.OrderStatusEnum;
import com.hxrfid.common.enums.UserType;
import com.hxrfid.project.domain.BsOrder;
import com.hxrfid.project.service.IBsOrderService;
import com.hxrfid.project.service.IBsProductService;
import com.hxrfid.system.service.ISysUserService;
import lombok.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

/**
 * 首页统计控制器
 */
@Validated
@RequiredArgsConstructor
@RequestMapping("/home")
@RestController
public class HomeController extends BaseController {

    private final IBsOrderService iBsOrderService;
    private final ISysUserService iSysUserService;
    private final IBsProductService iBsProductService;

    /**
     * 获取首页统计数据
     */
    @GetMapping("/index")
    public R index(@RequestParam(value = "startTime") String startTime, @RequestParam(value = "endTime") String endTime) {
        Map<String, Object> ajax = new HashMap<>();
        /** 今日数据 */
        String todayStr = DateUtil.format(DateUtil.date(), "yyyy-MM-dd");
        List<BsOrder> todayList = iBsOrderService.lambdaQuery().last("where order_status = '2' and DATE_FORMAT(pay_time,'%Y-%m-%d') = '" + todayStr + "'").list();
        // 今日订单总数
        ajax.put("todayOrderCount", todayList.size());
        // 今日销售总额
        ajax.put("todayOrderTotalPrice", todayList.stream().map(item -> NumberUtil.toBigDecimal(item.getRealPrice())).reduce(BigDecimal.ZERO, BigDecimal::add));
        /** 昨日数据 */
        String yesterdayStr = DateUtil.format(DateUtil.yesterday(), "yyyy-MM-dd");
        List<BsOrder> yesterdayList = iBsOrderService.lambdaQuery().last("where DATE_FORMAT(pay_time,'%Y-%m-%d') = '" + yesterdayStr + "'").list();
        // 昨日销售总额
        ajax.put("yesterdayOrderTotalPrice", yesterdayList.stream().map(item -> NumberUtil.toBigDecimal(item.getRealPrice())).reduce(BigDecimal.ZERO, BigDecimal::add));
        /** 订单数据 */
        // 待付款订单
        ajax.put("waitPayOrderCount", iBsOrderService.count(Wrappers.<BsOrder>lambdaQuery().eq(BsOrder::getOrderStatus, OrderStatusEnum.ONE.getCode())));
        // 待发货订单
        ajax.put("waitSendOrderCount", iBsOrderService.count(Wrappers.<BsOrder>lambdaQuery().eq(BsOrder::getOrderStatus, OrderStatusEnum.TWO.getCode())));
        // 待确认收货订单
        ajax.put("waitConfirmOrderCount", iBsOrderService.count(Wrappers.<BsOrder>lambdaQuery().eq(BsOrder::getOrderStatus, OrderStatusEnum.THREE.getCode())));
        // 已完成订单
        ajax.put("waitReceiveOrderCount", iBsOrderService.count(Wrappers.<BsOrder>lambdaQuery().eq(BsOrder::getOrderStatus, OrderStatusEnum.FOUR.getCode())));
        // 待退款订单
        ajax.put("waitRefundOrderCount", iBsOrderService.count(Wrappers.<BsOrder>lambdaQuery().eq(BsOrder::getOrderStatus, OrderStatusEnum.FIVE.getCode())));
        // 已退款订单
        ajax.put("refundedOrderCount", iBsOrderService.count(Wrappers.<BsOrder>lambdaQuery().eq(BsOrder::getOrderStatus, OrderStatusEnum.SIX.getCode())));
        // 全部商品数量
        ajax.put("productCount", iBsProductService.count());
        // 今日新增会员
        ajax.put("todayUserCount", iSysUserService.count(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUserType, UserType.APP_USER.getUserType()).last("and DATE_FORMAT(create_time,'%Y-%m-%d') = '" + todayStr + "'")));
        // 昨日新增会员
        ajax.put("yesterdayUserCount", iSysUserService.count(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUserType, UserType.APP_USER.getUserType()).last("and DATE_FORMAT(create_time,'%Y-%m-%d') = '" + yesterdayStr + "'")));
        // 本月新增会员
        String currMonth = DateUtil.format(DateUtil.date(), "yyyy-MM");
        ajax.put("monthUserCount", iSysUserService.count(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUserType, UserType.APP_USER.getUserType()).last("and DATE_FORMAT(create_time,'%Y-%m') = '" + currMonth + "'")));
        // 会员总数
        ajax.put("userCount", iSysUserService.count(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUserType, UserType.APP_USER.getUserType())));
        /** 本月订单数据 */
        List<BsOrder> list = iBsOrderService.list(Wrappers.<BsOrder>lambdaQuery().last("where DATE_FORMAT(pay_time,'%Y-%m') = '" + currMonth + "'"));
        // 本月订单总数
        ajax.put("monthOrderCount", list.size());
        // 本月销售总额
        ajax.put("monthOrderTotalPrice", list.stream().map(item -> NumberUtil.toBigDecimal(item.getRealPrice())).reduce(BigDecimal.ZERO, BigDecimal::add));
        /** 上月订单数据 */
        String lastMonth = DateUtil.format(DateUtil.offsetMonth(DateUtil.date(), -1), "yyyy-MM");
        List<BsOrder> lastList = iBsOrderService.list(Wrappers.<BsOrder>lambdaQuery().last("where DATE_FORMAT(pay_time,'%Y-%m') = '" + lastMonth + "'"));
        // 上月订单总数
        ajax.put("lastMonthOrderCount", lastList.size());
        // 上月销售总额
        ajax.put("lastMonthOrderTotalPrice", lastList.stream().map(item -> NumberUtil.toBigDecimal(item.getRealPrice())).reduce(BigDecimal.ZERO, BigDecimal::add));
        /** 本周订单数据 */
        String beginOfWeek = DateUtil.format(DateUtil.beginOfWeek(DateUtil.date()), "yyyy-MM-dd");
        String endOfWeek = DateUtil.format(DateUtil.endOfWeek(DateUtil.date()), "yyyy-MM-dd");
        List<BsOrder> weekList = iBsOrderService.list(Wrappers.<BsOrder>lambdaQuery().last("where DATE_FORMAT(pay_time,'%Y-%m-%d') between '" + beginOfWeek + "' and '" + endOfWeek + "'"));
        // 本周订单总数
        ajax.put("weekOrderCount", weekList.size());
        // 本周销售总额
        ajax.put("weekOrderTotalPrice", weekList.stream().map(item -> NumberUtil.toBigDecimal(item.getRealPrice())).reduce(BigDecimal.ZERO, BigDecimal::add));
        /** 上周订单数据 */
        String beginOfLastWeek = DateUtil.format(DateUtil.beginOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1)), "yyyy-MM-dd");
        String endOfLastWeek = DateUtil.format(DateUtil.endOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1)), "yyyy-MM-dd");
        List<BsOrder> lastWeekList = iBsOrderService.list(Wrappers.<BsOrder>lambdaQuery().last("where DATE_FORMAT(pay_time,'%Y-%m-%d') between '" + beginOfLastWeek + "' and '" + endOfLastWeek + "'"));
        // 上周订单总数
        ajax.put("lastWeekOrderCount", lastWeekList.size());
        // 上周销售总额
        ajax.put("lastWeekOrderTotalPrice", lastWeekList.stream().map(item -> NumberUtil.toBigDecimal(item.getRealPrice())).reduce(BigDecimal.ZERO, BigDecimal::add));
        /** 每日订单数量、订单金额 */
        List<DayVo> dayList = new ArrayList<>();
        List<BsOrder> everyList = iBsOrderService.list(Wrappers.<BsOrder>lambdaQuery().last("where DATE_FORMAT(pay_time,'%Y-%m-%d') between '" + startTime + "' and '" + endTime + "'"));
        List<DateTime> dateTimes = DateUtil.rangeToList(DateUtil.parse(startTime), DateUtil.parse(endTime), DateField.DAY_OF_MONTH);
        dateTimes.forEach(dateTime -> {
            String everyDay = DateUtil.format(dateTime, "yyyy-MM-dd");
            Stream<BsOrder> bsOrderStreamForSize = everyList.parallelStream().filter(bsOrder -> DateUtil.format(bsOrder.getCreateTime(), "yyyy-MM-dd").equals(everyDay));
            Stream<BsOrder> bsOrderStreamForPrice = everyList.parallelStream().filter(bsOrder -> DateUtil.format(bsOrder.getCreateTime(), "yyyy-MM-dd").equals(everyDay));
            dayList.add(DayVo.builder().day(everyDay).orderCount(bsOrderStreamForSize.count()).orderPrice(bsOrderStreamForPrice.map(item -> NumberUtil.toBigDecimal(item.getRealPrice())).reduce(BigDecimal.ZERO, BigDecimal::add)).build());
        });
        ajax.put("dayList", dayList);

        return R.ok(ajax);
    }

}

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
class DayVo {
    private String day;
    private Long orderCount;
    private BigDecimal orderPrice;
}
